package org.dairy.farms.interceptor.hibernate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dairy.farms.core.NandanaThreadLocal;
import org.dairy.farms.core.UserSession;
import org.dairy.farms.model.AuditInfo;
import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityMode;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: gduggira
 * Date: Jun 9, 2011
 * Time: 6:15:30 PM
 */
public class AuditInterceptor extends EmptyInterceptor {
    private static final Log logger = LogFactory.getLog(AuditInterceptor.class);


    /**
     * Default Constructor
     */
    public AuditInterceptor() {
        super();
    }

    public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames,
                          Type[] types) {
        return false;
    }

    public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
                                Object[] previousState, String[] propertyNames, Type[] types) throws CallbackException {
        UserSession userSession = NandanaThreadLocal.get();
        if (entity instanceof Auditable) {
            if (userSession == null) {
                throw new CallbackException("User session is not established");
            }
            AuditInfo ai = ((Auditable) entity).getAuditInfo();
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            if (ai == null) {
                ai = new AuditInfo();
                ai.setDateCreated(timestamp);
                ai.setCreatedBy(userSession.getPersonId());
            }
            ai.setDateModified(timestamp);
            ai.setModifiedBy(userSession.getPersonId());
        }
        return true;
    }

    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames,
                          Type[] types) throws CallbackException {
        UserSession userSession = NandanaThreadLocal.get();
        if (entity instanceof Auditable) {
            AuditInfo ai = ((Auditable) entity).getAuditInfo();
            if (ai == null)
                ai = new AuditInfo();//To be Revisited.
            if (userSession.getLoginName() == null) {
                throw new CallbackException("User session is not established");
            }
            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            ai.setDateCreated(timestamp);
            ai.setCreatedBy(userSession.getPersonId());
            ai.setDateModified(timestamp);
            ai.setModifiedBy(userSession.getPersonId());
        }
        return true;
    }

    public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames,
                         Type[] types) {
        // Do nothing
    }

    public void onCollectionRecreate(Object object, Serializable serializable) throws CallbackException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void onCollectionRemove(Object object, Serializable serializable) throws CallbackException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void onCollectionUpdate(Object object, Serializable serializable) throws CallbackException {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public void preFlush(Iterator entities) {
        // Do nothing
    }

    public void postFlush(Iterator entities) {
        // Do nothing
    }

    public Boolean isTransient(Object object) {
        //TODO: Determine what must be here
        return null;
    }

    public Boolean isUnsaved(Object entity) {
        //TODO: Determine what must be here
        return null;
    }

    public int[] findDirty(Object entity, Serializable id, Object[] currentState,
                           Object[] previousState, String[] propertyNames, Type[] types) {
        return null;
    }

    public Object instantiate(String string, EntityMode entityMode, Serializable serializable) throws CallbackException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public String getEntityName(Object object) throws CallbackException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Object getEntity(String string, Serializable serializable) throws CallbackException {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    public void afterTransactionBegin(Transaction transaction) {
        logger.debug("Transaction started");
    }

    public void beforeTransactionCompletion(Transaction transaction) {
        logger.debug("Transaction starting");
    }

    public void afterTransactionCompletion(Transaction transaction) {
        logger.debug("Transaction done");
    }

    public Object instantiate(Class clazz, Serializable id) {
        return null;
    }

}
